package com.lkd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.lkd.common.VMSystem;
import com.lkd.config.ConsulConfig;
import com.lkd.config.TopicConfig;
import com.lkd.contract.OrderCheck;
import com.lkd.contract.VendoutContract;
import com.lkd.contract.VendoutData;
import com.lkd.dao.OrderDao;
import com.lkd.feign.UserService;
import com.lkd.utils.DistributedLock;
import com.lkd.vo.PartnerVO;
import com.lkd.vo.PayVO;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.OrderEntity;
import com.lkd.exception.LogicException;
import com.lkd.feign.VMService;
import com.lkd.service.OrderService;

import com.lkd.vo.SkuVO;
import com.lkd.vo.VmVO;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    @Autowired
    private VMService vmService;
    @Autowired
    private UserService userService;
    @Autowired
    private MqttProducer mqttProducer;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ConsulConfig consulConfig;
    @Override
    public OrderEntity getByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(OrderEntity::getOrderNo,orderNo);
        return this.getOne(qw);
    }

    @Override
    public OrderEntity createOrder(PayVO payVO) {
        //判断商品是否售空
        if(!vmService.hasCapacity(payVO.getInnerCode(),Long.valueOf(payVO.getSkuId()))){
            throw new LogicException("商品已售空");
        }
        //分布式锁
        DistributedLock lock = new DistributedLock(consulConfig.getConsulRegisterHost(), consulConfig.getConsulRegisterPort());
        DistributedLock.LockContext lockContext = lock.getLock(payVO.getInnerCode() + "_" + payVO.getSkuId(), 60);
        if(!lockContext.isGetLock()){
            throw new LogicException("机器出货中，稍后再试");
        }
        redisTemplate.boundValueOps(VMSystem.VM_LOCK_KEY_PREF+payVO.getInnerCode()+"_"+payVO.getSkuId())
                .set(lockContext.getSession(),Duration.ofSeconds(60));
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOpenId(payVO.getOpenId());
        orderEntity.setStatus(VMSystem.ORDER_STATUS_CREATE);
        orderEntity.setPayStatus(VMSystem.PAY_STATUS_NOPAY);
        orderEntity.setOrderNo(payVO.getInnerCode()+System.nanoTime());//订单编号
        //根据售货机编号查询售货机信息 ,并复制给订单对象
        VmVO vmVO = vmService.getVMInfo(payVO.getInnerCode());
        BeanUtils.copyProperties(vmVO,orderEntity);
        orderEntity.setAddr(vmVO.getNodeAddr());
        //根据商品编号查询商品信息，并复制给订单对象
        SkuVO sku = vmService.getSku(payVO.getSkuId());
        BeanUtils.copyProperties(sku,orderEntity);
        orderEntity.setAmount(sku.getRealPrice());
        //计算合作商账单分账金额
        PartnerVO partner = userService.getPartner(vmVO.getOwnerId());
        BigDecimal bd = new BigDecimal(orderEntity.getAmount());
        int i = bd.multiply(new BigDecimal(partner.getRatio()))
                .divide(new BigDecimal(100), 0, RoundingMode.HALF_UP).intValue();
        orderEntity.setPrice(i);
        save(orderEntity);
        //发送消息
        OrderCheck orderCheck = new OrderCheck();
        orderCheck.setOrderNo(orderEntity.getOrderNo());
        try {
            mqttProducer.send("$delayed/300/"+ TopicConfig.ORDER_CHECK_TOPIC,2,orderCheck);
        } catch (Exception e) {
            log.error("发送创建订单消息失败",e);
        }
        return orderEntity;
    }

    @Override
    public void outShop(String orderId, Long skuId, String innerCode) {
        VendoutContract vendoutContract = new VendoutContract();
        VendoutData vendoutData = new VendoutData();
        vendoutContract.setInnerCode(innerCode);
        vendoutData.setOrderNo(orderId);
        vendoutData.setSkuId(skuId);
        vendoutContract.setVendoutData(vendoutData);
        try {
            log.info("订单发送消息售货机微服务成功");
            mqttProducer.send(TopicConfig.VMS_VENDOUT_TOPIC,2,vendoutContract);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

}
